package com.example.springsecuritycsrf.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import org.apache.commons.collections4.MapUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;

public class SimpleAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private final RedisTemplate<String,String> redisTemplate;
    private final AuthenticationManager authenticationManager;

    public SimpleAuthenticationFilter(AuthenticationManager authenticationManager, RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
        this.authenticationManager = authenticationManager;
    }

    @SneakyThrows
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        Map<String,String> map = JSON.parseObject(request.getInputStream(), StandardCharsets.UTF_8,Map.class);
        return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(MapUtils.getString(map,"username"),MapUtils.getString(map,"password")));
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        SecurityContextHolder.getContext().setAuthentication(authResult);
        UserDetails userDetails = (UserDetails) authResult.getPrincipal();
        System.err.println(JSONObject.toJSONString(userDetails));
        String redisKey = "user_" + userDetails.getUsername();
        String csrfToken = redisTemplate.opsForList().leftPop(redisKey);
        response.setHeader("csrf_token",csrfToken);
    }
}
